package cluster

import (
	"errors"
	"fmt"
	"github.com/avast/retry-go"
	"os"
	"path"
	"wf-deploy-agent/conf"
	"wf-deploy-agent/infra"
	"wf-deploy-agent/plugin"
	"wf-deploy-agent/remote"
	"wf-deploy-agent/util"
)

// EnableSyncPlugin 启用插件同步
func EnableSyncPlugin() {
	conf.CF.Task.Sync.Plugin = true
}

// DisableSyncPlugin 禁用插件同步
func DisableSyncPlugin() {
	conf.CF.Task.Sync.Plugin = false
}

// SyncPlugin 同步插件
func SyncPlugin() {
	if !conf.CF.Task.Sync.Plugin {
		return
	}

	infra.Logger.Infoln("开始同步插件")

	loader := plugin.NewLoader()
	plugins := remote.Api.FetchPluginSummary()
	for _, _plugin := range plugins {
		if err := recover(); err != nil {
			infra.Logger.Errorln(err)
			continue
		}

		if !conf.CF.Task.Sync.Plugin {
			break
		}

		infra.Logger.Debug(util.ToJson(_plugin))

		// 通过计算插件MD5值验证插件是否完整
		dest := path.Join(conf.GetPluginDir(), _plugin.Name)
		if util.Exists(dest) && _plugin.MD5 != "" {
			md5 := util.GetFileMD5(dest)
			if md5 == _plugin.MD5 {
				infra.Logger.Infof("插件【%s】本机版本与远程版本一致，无需更新", _plugin.Name)
				continue
			}
		}

		_ = retry.Do(
			func() error {
				tmp := dest + ".tmp"
				url := remote.GetPluginDownloadUrl(_plugin)
				infra.Logger.Infof("开始下载插件【%s】,地址:%s", _plugin.Name, url)

				err := loader.Download(url, conf.GetPluginDir(), _plugin.Name, 10)
				if err != nil {
					infra.Logger.Errorf("下载插件【%s】发生错误:%s", _plugin.Name, err)
					return err
				}

				if _plugin.MD5 != "" {
					md5 := util.GetFileMD5(tmp)
					if md5 != _plugin.MD5 {
						err = errors.New(fmt.Sprintf("local file 【%s】 md5 is %s, but original md5 is %s", tmp, md5, _plugin.MD5))
						return err
					}
				}

				if !conf.CF.Task.Sync.Plugin {
					return nil
				}

				util.Acquire(_plugin.Name).Lock()
				err = os.Rename(tmp, dest)
				util.Acquire(_plugin.Name).Unlock()

				return err
			},
			retry.RetryIf(func(err error) bool {
				return conf.CF.Task.Sync.Plugin
			}),
		)
	}
	infra.Logger.Infoln("结束同步插件")
}
